package net.lab1024.sa.admin.module.business.aps.controller;

import cn.dev33.satoken.annotation.SaCheckPermission;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import net.lab1024.sa.admin.module.business.aps.domain.optaplanner.ScheduleSolution;
import net.lab1024.sa.admin.module.business.aps.domain.vo.ApsScheduleResultVO;
import net.lab1024.sa.admin.module.business.aps.service.ApsConvertService;
import net.lab1024.sa.admin.module.business.aps.service.ApsOptaPlannerService;
import net.lab1024.sa.base.common.domain.ResponseDTO;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.Map;
import java.util.concurrent.CompletableFuture;

/**
 * APS排程控制器
 * 提供生产排程优化的REST API接口
 *
 * @Author 1024创新实验室
 * @Date 2025-01-28
 * @Wechat zhuoda1024
 * @Email lab1024@163.com
 * @Copyright <a href="https://1024lab.net">1024创新实验室</a>
 */
@Slf4j
@RestController
@Tag(name = "APS排程管理")
public class ApsController {

    @Autowired
    private ApsOptaPlannerService apsOptaPlannerService;
    
    @Autowired
    private ApsConvertService apsConvertService;

    @Operation(summary = "创建示例排程问题")
    @GetMapping("/aps/sample/create")
    @SaCheckPermission("aps:sample:create")
    public ResponseDTO<ScheduleSolution> createSampleProblem() {
        try {
            ScheduleSolution problem = apsOptaPlannerService.createSampleProblem();
            return ResponseDTO.ok(problem);
        } catch (Exception e) {
            log.error("创建示例排程问题失败", e);
            return ResponseDTO.userErrorParam("创建示例排程问题失败: " + e.getMessage());
        }
    }

    @Operation(summary = "同步求解排程问题")
    @PostMapping("/aps/solve/sync")
    @SaCheckPermission("aps:solve:sync")
    public ResponseDTO<ScheduleSolution> solveScheduleSync(@RequestBody ScheduleSolution problem) {
        try {
            log.info("接收到同步排程求解请求: {}", problem.getSolutionName());
            ScheduleSolution solution = apsOptaPlannerService.solveSchedule(problem);
            return ResponseDTO.ok(solution);
        } catch (Exception e) {
            log.error("同步求解排程问题失败", e);
            return ResponseDTO.userErrorParam("同步求解排程问题失败: " + e.getMessage());
        }
    }

    @Operation(summary = "异步求解排程问题")
    @PostMapping("/aps/solve/async")
    @SaCheckPermission("aps:solve:async")
    public ResponseDTO<String> solveScheduleAsync(@RequestBody ScheduleSolution problem) {
        try {
            log.info("接收到异步排程求解请求: {}", problem.getSolutionName());
            
            CompletableFuture<ScheduleSolution> future = apsOptaPlannerService.solveScheduleAsync(problem);
            
            // 异步处理结果
            future.whenComplete((solution, throwable) -> {
                if (throwable != null) {
                    log.error("异步求解排程问题失败", throwable);
                } else {
                    log.info("异步求解排程问题完成: {}", solution.getSolutionSummary());
                    // 这里可以添加结果通知逻辑，比如发送消息到前端或保存到数据库
                }
            });
            
            return ResponseDTO.ok("异步求解任务已提交，请稍后查看结果");
        } catch (Exception e) {
            log.error("提交异步求解任务失败", e);
            return ResponseDTO.userErrorParam("提交异步求解任务失败: " + e.getMessage());
        }
    }

    @Operation(summary = "求解示例排程问题")
    @PostMapping("/aps/sample/solve")
    @SaCheckPermission("aps:sample:solve")
    public ResponseDTO<ScheduleSolution> solveSampleProblem() {
        try {
            log.info("开始求解示例排程问题");
            
            // 创建示例问题
            ScheduleSolution problem = apsOptaPlannerService.createSampleProblem();
            
            // 求解问题
            ScheduleSolution solution = apsOptaPlannerService.solveSchedule(problem);
            
            log.info("示例排程问题求解完成");
            return ResponseDTO.ok(solution);
        } catch (Exception e) {
            log.error("求解示例排程问题失败", e);
            return ResponseDTO.userErrorParam("求解示例排程问题失败: " + e.getMessage());
        }
    }

    @Operation(summary = "验证排程解决方案")
    @PostMapping("/aps/solution/validate")
    @SaCheckPermission("aps:solution:validate")
    public ResponseDTO<Boolean> validateSolution(@RequestBody ScheduleSolution solution) {
        try {
            boolean isValid = apsOptaPlannerService.validateSolution(solution);
            return ResponseDTO.ok(isValid);
        } catch (Exception e) {
            log.error("验证排程解决方案失败", e);
            return ResponseDTO.userErrorParam("验证排程解决方案失败: " + e.getMessage());
        }
    }

    @Operation(summary = "获取排程统计信息")
    @PostMapping("/aps/solution/statistics")
    @SaCheckPermission("aps:solution:statistics")
    public ResponseDTO<String> getScheduleStatistics(@RequestBody ScheduleSolution solution) {
        try {
            String statistics = apsOptaPlannerService.getScheduleStatistics(solution);
            return ResponseDTO.ok(statistics);
        } catch (Exception e) {
            log.error("获取排程统计信息失败", e);
            return ResponseDTO.userErrorParam("获取排程统计信息失败: " + e.getMessage());
        }
    }

    @Operation(summary = "测试OptaPlanner功能")
    @GetMapping("/aps/test")
    @SaCheckPermission("aps:test")
    public ResponseDTO<String> testOptaPlanner() {
        try {
            log.info("开始测试OptaPlanner功能");
            
            // 创建并求解示例问题
            ScheduleSolution problem = apsOptaPlannerService.createSampleProblem();
            ScheduleSolution solution = apsOptaPlannerService.solveSchedule(problem);
            
            // 验证解决方案
            boolean isValid = apsOptaPlannerService.validateSolution(solution);
            
            // 获取统计信息
            String statistics = apsOptaPlannerService.getScheduleStatistics(solution);
            
            StringBuilder result = new StringBuilder();
            result.append("=== OptaPlanner功能测试结果 ===\n");
            result.append("解决方案有效性: ").append(isValid ? "有效" : "无效").append("\n");
            result.append("\n").append(statistics);
            
            log.info("OptaPlanner功能测试完成");
            return ResponseDTO.ok(result.toString());
        } catch (Exception e) {
            log.error("测试OptaPlanner功能失败", e);
            return ResponseDTO.userErrorParam("测试OptaPlanner功能失败: " + e.getMessage());
        }
    }

    @Operation(summary = "获取排程结果（VO格式）")
    @PostMapping("/aps/solution/result")
    @SaCheckPermission("aps:solution:result")
    public ResponseDTO<ApsScheduleResultVO> getScheduleResult(@RequestBody ScheduleSolution solution) {
        try {
            ApsScheduleResultVO resultVO = apsConvertService.convertToResultVO(solution);
            return ResponseDTO.ok(resultVO);
        } catch (Exception e) {
            log.error("获取排程结果失败", e);
            return ResponseDTO.userErrorParam("获取排程结果失败: " + e.getMessage());
        }
    }

    @Operation(summary = "求解并获取排程结果（VO格式）")
    @PostMapping("/aps/solve/result")
    @SaCheckPermission("aps:solve:result")
    public ResponseDTO<ApsScheduleResultVO> solveAndGetResult(@RequestBody ScheduleSolution problem) {
        try {
            log.info("接收到排程求解请求: {}", problem.getSolutionName());
            
            // 求解问题
            ScheduleSolution solution = apsOptaPlannerService.solveSchedule(problem);
            
            // 转换为VO格式
            ApsScheduleResultVO resultVO = apsConvertService.convertToResultVO(solution);
            
            return ResponseDTO.ok(resultVO);
        } catch (Exception e) {
            log.error("求解排程问题失败", e);
            return ResponseDTO.userErrorParam("求解排程问题失败: " + e.getMessage());
        }
    }

    @Operation(summary = "求解示例问题并获取结果（VO格式）")
    @PostMapping("/aps/sample/solve/result")
    @SaCheckPermission("aps:sample:solve:result")
    public ResponseDTO<ApsScheduleResultVO> solveSampleAndGetResult() {
        try {
            log.info("开始求解示例排程问题并获取VO结果");
            
            // 创建示例问题
            ScheduleSolution problem = apsOptaPlannerService.createSampleProblem();
            
            // 求解问题
            ScheduleSolution solution = apsOptaPlannerService.solveSchedule(problem);
            
            // 转换为VO格式
            ApsScheduleResultVO resultVO = apsConvertService.convertToResultVO(solution);
            
            log.info("示例排程问题求解完成，返回VO结果");
            return ResponseDTO.ok(resultVO);
        } catch (Exception e) {
            log.error("求解示例排程问题失败", e);
            return ResponseDTO.userErrorParam("求解示例排程问题失败: " + e.getMessage());
        }
    }

    @Operation(summary = "获取甘特图数据")
    @PostMapping("/aps/chart/gantt")
    @SaCheckPermission("aps:chart:gantt")
    public ResponseDTO<Map<String, Object>> getGanttData(@RequestBody ScheduleSolution solution) {
        try {
            Map<String, Object> ganttData = apsConvertService.generateGanttData(solution);
            return ResponseDTO.ok(ganttData);
        } catch (Exception e) {
            log.error("获取甘特图数据失败", e);
            return ResponseDTO.userErrorParam("获取甘特图数据失败: " + e.getMessage());
        }
    }

    @Operation(summary = "获取资源负载图数据")
    @PostMapping("/aps/chart/resource-load")
    @SaCheckPermission("aps:chart:resource-load")
    public ResponseDTO<Map<String, Object>> getResourceLoadData(@RequestBody ScheduleSolution solution) {
        try {
            Map<String, Object> loadData = apsConvertService.generateResourceLoadData(solution);
            return ResponseDTO.ok(loadData);
        } catch (Exception e) {
            log.error("获取资源负载图数据失败", e);
            return ResponseDTO.userErrorParam("获取资源负载图数据失败: " + e.getMessage());
        }
    }

    @Operation(summary = "获取APS系统状态")
    @GetMapping("/aps/status")
    @SaCheckPermission("aps:status")
    public ResponseDTO<String> getApsStatus() {
        try {
            StringBuilder status = new StringBuilder();
            status.append("=== APS系统状态 ===\n");
            status.append("OptaPlanner版本: 9.44.0.Final\n");
            status.append("系统状态: 运行中\n");
            status.append("支持功能:\n");
            status.append("- 生产任务排程优化\n");
            status.append("- 资源分配优化\n");
            status.append("- 时间约束处理\n");
            status.append("- 优先级调度\n");
            status.append("- 前置任务依赖\n");
            status.append("- 资源容量限制\n");
            status.append("- 成本优化\n");
            status.append("\n=== API接口 ===\n");
            status.append("- GET  /aps/sample/create - 创建示例问题\n");
            status.append("- POST /aps/solve/sync - 同步求解\n");
            status.append("- POST /aps/solve/async - 异步求解\n");
            status.append("- POST /aps/sample/solve - 求解示例问题\n");
            status.append("- POST /aps/solve/result - 求解并获取VO结果\n");
            status.append("- POST /aps/chart/gantt - 获取甘特图数据\n");
            status.append("- POST /aps/chart/resource-load - 获取资源负载数据\n");
            
            return ResponseDTO.ok(status.toString());
        } catch (Exception e) {
            log.error("获取APS系统状态失败", e);
            return ResponseDTO.userErrorParam("获取APS系统状态失败: " + e.getMessage());
        }
    }
}